

#include "prefix_tree.h"
#include "path.h"
#include "itf_mc.h"

#include "mex.h"


void itf_mc(markovChain *mc, int nrhs, const mxArray *prhs[]) {
    
    int n_evclk;
    const mxArray *SData, *EData, *ESData, *pData, *GData;
    
    if (nrhs < 5)
        mexErrMsgTxt("The number of arguments are not correct.");
    
    /* S array - States id */
    SData = prhs[0];
    mc->S = mxGetPr(SData);
    mc->n_S = (int) mxGetN(SData);
    printf("\t n_S: %d\n", mc->n_S);
    
    /* E array - Events id */
    EData = prhs[1];
    mc->E = mxGetPr(EData);
    mc->n_E = (int)mxGetN(EData);
    printf("\t n_E: %d\n", mc->n_E);
    
    /* ES array - for all s: for all i: Event(i) in state(s)*/
    ESData = prhs[2]; /* Matrix*/
    mc->ES = mxGetPr(ESData);
    mc->r_ES = (int)mxGetM(ESData);
    mc->c_ES = (int)mxGetN(ESData);
    printf("\t r_ES,c_ES: %d %d\n", mc->r_ES, mc->c_ES);
    
    if (mc->r_ES != mc->n_S)
        mexErrMsgTxt("The size of ES matrix not match.");
    
    if (mc->c_ES != mc->n_E)
        mexErrMsgTxt("The size of ES matrix not match.");
    
    /* Probabilistic matrix - P(s' | s and e*) */
    pData = prhs[3];
    mc->p = mxGetPr(pData);
    /*for (z=0; z<n_E; z++)
        for (j=0; j<n_S; j++)
            for (i=0; i<n_S; i++)
        mexPrintf("T%d: %f \n", i, p[(i+(j*n_S))+(n_S*n_S*z)]);*/
    
    mc->r_p = (int)mxGetN(pData);
    mc->c_p = (int)mxGetM(pData);
    printf("\t r_p,c_p: %d %d\n", mc->r_p, mc->c_p);
    
    /* Clock distribution matrix */
    GData = prhs[4];
    n_evclk = (int)mxGetM(GData);
    printf("\t r_G,c_G: %d %d\n", mxGetN(GData), n_evclk);
}

void itf_path(struct samples *sr, int nrhs, const mxArray *prhs[]) {
    
    unsigned int i, p, n_sample, n_row, n_col, event;
    const mxArray *sampleR, *path_cell;
    double *path, time;
    path_el tmp_el;
    path_n *nnode;
    
    if (!(nrhs > 1))
        mexErrMsgTxt("The number of arguments do not match for sample executions.");
    
    if (mxIsComplex(prhs[0])|| mxIsClass(prhs[0],"sparse") || mxIsChar(prhs[0])) {
        mexErrMsgTxt("'path' input  must be real, full, and non string.");
    }
        
    /* sample runs */
    sampleR = prhs[0];
    n_sample = (int) mxGetM(sampleR);
    printf("\t r_G,c_G: %d %d\n", mxGetN(sampleR), n_sample);
    
    sr->arrayPaths = malloc(sizeof(path_l *) * n_sample);
    sr->n = n_sample;
    
    for (i = 0; i < n_sample; i++) {
        
        /* Event distribution name */
        path_cell = mxGetCell(sampleR, i);
        
        if (mxIsDouble(path_cell) != 1)
            mexErrMsgTxt("Input cell must be an array.");
        
        path = (double *) mxGetPr(path_cell);
        n_col = (int) mxGetN(path_cell);
        n_row = (int) mxGetM(path_cell);
        
        sr->arrayPaths[i] = dll_path_newlist();
        
        /*mexPrintf("Get Data %d %d ...\n", n_row, n_col);*/
        
        /* Create a new path */
        for(p=0; p<n_row; p++) {
            event = (unsigned int) path[p+(n_row*0)];
            time = (double) path[p+(n_row*1)];
            
            tmp_el.ev_id = event;
            tmp_el.clk = time;
            tmp_el.t_node = NULL;
            
            nnode = dll_path_newnode(tmp_el);
            dll_path_insertend(sr->arrayPaths[i], nnode);
        }
        
    }
}

void free_itf_path(struct samples *sr) {
    unsigned int i;
    
    for (i=0; i < sr->n; i++) {
        dll_path_freelist(sr->arrayPaths[i]);
    }
    
    free(sr->arrayPaths);
}

void setparameters(struct parameters *param, char *parameterid, unsigned int parametervalue) {
    
    if (strcmp(parameterid, "method") == 0)
        param->method = parametervalue;
    else if (strcmp(parameterid, "gui") == 0)
        param->gui = parametervalue;
    else
        mexErrMsgTxt("The parameter 'id' is not recognized.");
    
}

void free_parameters(struct parameters *p) {
    free(p);
}

struct parameters *create_parameters() {
    struct parameters *param = ( struct parameters *) malloc(sizeof(struct parameters));
    param->gui = 0;
    param->method = 0;
}

